use std::time::Duration;

use axum::{error_handling::HandleErrorLayer, Router};
use tower::{buffer::BufferLayer, limit::RateLimitLayer, ServiceBuilder};
use tower_http::trace::{self, TraceLayer};
use tracing::Level;
use axum_tracing_opentelemetry::middleware::{OtelAxumLayer, OtelInResponseLayer};



use super::{web_handler, web_router};

pub(crate) fn register() -> Router {
    // layer police
    let layer_police = ServiceBuilder::new()
        .layer(HandleErrorLayer::new(web_handler::police_error))
        .layer(BufferLayer::new(2048))
        .layer(RateLimitLayer::new(100, Duration::from_secs(1)))
        .timeout(Duration::from_secs(5));
    // layer trace
    let layer_trace = TraceLayer::new_for_http()
        .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
        .on_request(trace::DefaultOnRequest::new().level(Level::INFO))
        .on_response(trace::DefaultOnResponse::new().level(Level::INFO));
    // layer metric
    let layer_metric = OtelAxumLayer::default();
    let layer_metric_response = OtelInResponseLayer::default();
    // router
    Router::new()
        // router
        .nest("/user", web_router::group_user())
        .nest("/test", web_router::group_test())
        // fallback
        .fallback(web_handler::not_found_error)
        // middleware
        .layer(layer_trace)
        .layer(layer_police)
        .layer(layer_metric_response)
        .layer(layer_metric)
}
